/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#pragma once

#ifdef _WIN32
#define ExportSymbol  __declspec(dllexport)
#else
#define ExportSymbol
#endif

#include <chrono>
#include <numeric>
#include <iostream>
#include <functional>
#include <thread>
#include <atomic>
#include <memory>
#include <condition_variable>
#include <vector>

namespace NahidaProject {
	class ExportSymbol HighPrecisionTimer {
	private:
		std::chrono::high_resolution_clock::time_point startTime;
		std::chrono::high_resolution_clock::time_point endTime;
		bool running;

	public:
		HighPrecisionTimer() : running(false) {

		}

		void Start();
		void Stop();
		long long ElapsedNanoSeconds() const;
		long long ElapsedMicroSeconds() const;
		long long ElapsedMilliSeconds() const;
		double ElapsedSeconds() const;
		void Reset();
	};


	class ExportSymbol CallbackTimer {
	private:
		std::atomic<bool> running;
		std::thread timerThread;
		std::function<void()> callback;
		std::chrono::milliseconds interval;
		std::mutex mutex;
		std::condition_variable conditionVariable;

	public:
		explicit CallbackTimer(std::chrono::milliseconds interval, std::function<void()> callback) : running(false), callback(callback), interval(interval) {

		}

		~CallbackTimer() {
			Stop();
		}

		void Start();
		void Stop();
		void SetCallback(std::function<void()> callback);
		void SetInterval(std::chrono::milliseconds interval);
	};

	class ExportSymbol PrecisionDelay {
	public:
		static void DelayNanoSeconds(long long nanoseconds);
		static void DelayMicroSeconds(long long microseconds);
		static void DelayMilliSeconds(long long milliseconds);
	};

	class ExportSymbol PerformanceTimer {
	private:
		std::vector<double> measurements;
		HighPrecisionTimer timer;

	public:
		PerformanceTimer() = default;

		void Begin();
		void End();
		double AverageTime() const;
		double MinimumTime() const;
		double MaximumTime() const;
		size_t Count() const;
		void Clear();
		void PrintStatistics() const;
	};
}